package com.le.tester.tip;

import java.math.BigDecimal;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.StampedLock;

/**
 * createTime：2022/8/18 15:58
 * description：多线程执行stampedLock
 */
public class StampedLockUse {

    private BigDecimal balance = new BigDecimal(1000);

    public void execStampLock() {
        StampedLock lock = new StampedLock();

        Runnable w = () -> {
            //更新余额
            long stamp = lock.writeLock();
            setBalance(getBalance().add(BigDecimal.valueOf(1000)));
            System.out.println("write:" + getBalance());
            lock.unlockWrite(stamp);
        };

        Runnable r = () -> {
            //如果拿不到锁的话，则返回0，stamp在获取到锁的过程中应该全局使用
            long stamp = lock.tryOptimisticRead();

            if (!lock.validate(stamp)) {
                //可以拿到锁
                stamp = lock.readLock();
                try {
                    System.out.println("read:" + getBalance());
                } finally {
                    lock.unlockRead(stamp);
                }
            } else {
                System.out.println("optimistic read fails");
            }
        };
        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 50; i++) {
            executor.submit(w);
            executor.submit(r);
        }
    }

    public BigDecimal getBalance() {
        return balance;
    }

    public void setBalance(BigDecimal balance) {
        this.balance = balance;
    }

    public static void main(String[] args) {
        new StampedLockUse().execStampLock();
    }
}
